package main

import (
	"bufio"
	"errors"
	"fmt"
	"net/smtp"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	//	"time"
)

/*
args:
-m smtp server address
-s mail sender address
-r mail receiver addresses seperated by comma(,)
-c method server count (inlcuding background methodserver)
-w windchill home which equas WT_HOME in Windchill environment variables

-h help information
*/

var smtpServer string = "smtpinternal.lenovo.com"
var mailSender string = "wtmonitor_tool@lenovo.com"
var mailReceivers []string = []string{"zhaoxp2@lenovo.com", "liuxt2@lenovo.com", "zhangll9@lenovo.com"}
var wtHome = ""
var methodServerCount = 0

func main() {
	//fmt.Println("Windchill System Monitor Tool!")
	//fmt.Println("Author:zhaoxp")
	args := os.Args

	err := autoHandle()
	if err != nil {
		fmt.Println("error during authoHandle : ", err)
		return
	}
	handleArgs(args)
	printAllPropertis()
	err = monitorOSProcess()
	if err != nil {
		sendMail()
	}
}

func sendMail() {
	fmt.Println("send mail ----------")
	msg := []byte("To: " + strings.Join(mailReceivers, ";") + "\r\nFrom: " + mailSender + "<" + mailSender + ">\r\nSubject:" + "Subject" + "\r\n" + "Content-Type: text/plain; charset=UTF-8\r\n" + "\r\n\r\n" + "body")
	auth := smtp.PlainAuth("", mailSender, "", smtpServer)
	err := smtp.SendMail(smtpServer+":25", auth, mailSender, mailReceivers, msg)
	fmt.Println("sendmail err:", err)
}

func autoHandle() error {
	if wtHome == "" {
		ptcHomePath := "/apphome/ptc"
		ptcHomePath = "D:\\temp"
		ptcDir, err := os.Open(ptcHomePath)
		if err != nil {
			//fmt.Println("Read "+ptcHomePath+" error:", err)
			return err
		}
		dirNames, err := ptcDir.Readdirnames(0)
		if err != nil {
			//fmt.Println("Read dir name error of ", ptcHomePath, ":", err)
			return err
		}
		wcHomeName := ""
		wcVer := 0.0
		for _, name := range dirNames {
			if match, _ := regexp.MatchString("^Windchill_[0-9]{1,2}\\.[0-9]$", name); match {
				if ver, _ := strconv.ParseFloat(name[10:len(name)], 32); ver > wcVer {
					wcHomeName = name
					wcVer = ver
				}

			}
		}
		if wcHomeName == "" {
			return errors.New("WT_HOME could not be identified!")
		}
		wtHome = ptcHomePath + string(os.PathSeparator) + wcHomeName + string(os.PathSeparator) + "Windchill"
	}

	//fmt.Println("WT_HOME", wtHome)
	file, err := os.Open(wtHome + string(os.PathSeparator) + "codebase" + string(os.PathSeparator) + "wt.properties")
	if err != nil {
		fmt.Println("wt.properties read error:", err)
	}
	defer file.Close()
	reader := bufio.NewReader(file)
	for {
		linebytes, _, err := reader.ReadLine()
		//fmt.Println(string(linebytes), isPrefix, err)
		if err != nil {
			break
		}
		line := string(linebytes)
		//wt.manager.monitor.start.MethodServer=4
		//wt.manager.monitor.services=BackgroundMethodServer BackgroundMethodServer1 BackgroundMethodServer2 BackgroundMethodServer3 BackgroundMethodServer4 BackgroundMethodServer5
		//wt.mail.mailhost=smtpinternal.lenovo.com
		msCountPrefix := "wt.manager.monitor.start.MethodServer="
		servicePrefix := "wt.manager.monitor.services="
		mailHostPrefix := "wt.mail.mailhost="
		if strings.HasPrefix(line, msCountPrefix) {
			methodServerCount, _ = strconv.Atoi(line[len(msCountPrefix):len(line)])
		}
		if strings.HasPrefix(line, servicePrefix) {
			values := strings.Split(line[len(servicePrefix):len(line)], " ")
			count := 0
			for _, v := range values {
				if b, _ := regexp.MatchString("^BackgroundMethodServer[0-9]*", v); b {
					count++
				}
			}
			methodServerCount = methodServerCount + count
		}
		if strings.HasPrefix(line, "wt.mail.mailhost=") {
			if tmp := strings.Trim(line[len(mailHostPrefix):len(line)], " "); len(tmp) > 0 {
				smtpServer = tmp
			}
		}
	}
	//fmt.Println("all methodServer Count=", methodServerCount)
	//fmt.Println("smtpServer", smtpServer)
	return nil

}

func monitorOSProcess() error {
	out, err := exec.Command("/bin/sh", "-c", "ps -ef|grep -v grep|egrep '(wt.method.MethodServerMain|wt.manager.ServerManagerMain)'").Output()
	if err != nil {
		fmt.Println("OS command runnign error:", err)
		return err
	}
	msCount, err := strconv.Atoi(string(out))
	if err != nil {
		fmt.Println("error during strconv.Atoi()", err)
		return nil
	}
	if msCount != (methodServerCount + 1) {
		return errors.New("ServerManager and MethodServer number not correct, current is " + string(msCount))
	}
	return nil
}

func handleArgs(args []string) {
	for i := 1; i < len(args); i++ {
		//fmt.Println("i", args[i])
		if strings.ToLower(args[i]) == "-h" {
			printHelpInfo()
			os.Exit(0)
		}
		if strings.ToLower(args[i]) == "-m" {
			if i+1 < len(args) && !strings.HasPrefix(args[i+1], "-") {
				smtpServer = args[i+1]
				i++
			}
		}
		if strings.ToLower(args[i]) == "-s" {
			if i+1 < len(args) && !strings.HasPrefix(args[i+1], "-") {
				mailSender = args[i+1]
				i++
			}
		}
		if strings.ToLower(args[i]) == "-r" {
			if i+1 < len(args) && !strings.HasPrefix(args[i+1], "-") {
				mailReceivers = strings.Split(args[i+1], ",")
				i++
			}
		}
		if strings.ToLower(args[i]) == "-c" {
			if i+1 < len(args) && !strings.HasPrefix(args[i+1], "-") {
				methodServerCount, _ = strconv.Atoi(args[i+1])
				i++
			}
		}
		if strings.ToLower(args[i]) == "-w" {
			if i+1 < len(args) && !strings.HasPrefix(args[i+1], "-") {
				wtHome = args[i+1]
				i++
			}
		}
	}
}

func printAllPropertis() {
	fmt.Println("SMTP server:", smtpServer)
	fmt.Println("Mail sender:", mailSender)
	fmt.Println("Mail receivers:", mailReceivers)
}

func printHelpInfo() {
	fmt.Println("This tool is used to monitor Windchill system.")
	fmt.Println("Usage:")
	fmt.Println("  -m  smtp server address")
	fmt.Println("  -s  mail sender address")
	fmt.Println("  -r  mail receiver addresses seperated by comma(,)")
	fmt.Println("  -c  method server count (inlcuding background methodserver)")
	fmt.Println("  -w  windchill home which equas WT_HOME in Windchill environment variables")
	fmt.Println("  -h  help information")
	fmt.Println("")
	fmt.Println("Monitor item:")
	fmt.Println("1 Windchill process number")
	fmt.Println("")
	fmt.Println("")
	fmt.Println("Attention:")
	fmt.Println("This tool will read information in Windchill home to get properties. But command arguments have highest priority and will overwrite properties from Windchill home.")
}
